package com.lintf.bot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lintf.bot.domain.BotEating;
import com.lintf.bot.domain.constant.Constant;
import com.lintf.bot.domain.dto.BotEatingAddDTO;
import com.lintf.bot.domain.dto.BotEatingListDTO;
import com.lintf.bot.domain.dto.BotEatingUpdateDTO;
import com.lintf.bot.domain.enums.NoticeTypeEnums;
import com.lintf.bot.domain.enums.SysFileTypeEnums;
import com.lintf.bot.domain.vo.BotEatingListVo;
import com.lintf.bot.domain.vo.BotEatingOwnListVo;
import com.lintf.bot.mapper.BotEatingMapper;
import com.lintf.bot.notice.NoticeUtils;
import com.lintf.bot.service.IBotEatingService;
import com.lintf.common.core.domain.entity.SysUser;
import com.lintf.common.utils.SecurityUtils;
import com.lintf.common.utils.uuid.IdUtils;
import com.lintf.system.domain.SysFileInfo;
import com.lintf.system.service.ISysFileInfoService;
import com.lintf.system.service.ISysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author lintf
 * @description 针对表【bot_eating】的数据库操作Service实现
 * @createDate 2024-01-07 00:26:01
 */
@Service
public class BotEatingServiceImpl extends ServiceImpl<BotEatingMapper, BotEating>
        implements IBotEatingService {

    @Autowired
    private ISysFileInfoService sysFileInfoService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private NoticeUtils noticeUtils;

    @Override
    public List<BotEatingListVo> list(BotEatingListDTO dto) {
        LambdaQueryWrapper<BotEating> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(BotEating::getCreateTime);
        if (dto.getId() != null){
            wrapper.eq(BotEating::getId,dto.getId());
        }
        if (dto.getGroupId() != null) {
            wrapper.eq(BotEating::getGroupId, dto.getGroupId());
        } else if(dto.getId() == null){
            wrapper.eq(BotEating::getGroupId, 0);
        }
        if (StringUtils.isNotEmpty(dto.getDateSearchValue())) {
            LocalDateTime startTime = LocalDateTime.parse(dto.getDateSearchValue() + "T00:00:00");
            LocalDateTime endTime = LocalDateTime.parse(dto.getDateSearchValue() + "T23:59:59");
            wrapper.ge(BotEating::getCreateTime, startTime)
                    .le(BotEating::getCreateTime, endTime);
        }
        Page<BotEating> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        List<BotEating> list = baseMapper.selectPage(page, wrapper).getRecords();
        return this.getSysFile(list);
    }

    private List<BotEatingListVo> getSysFile(List<BotEating> list) {
        LambdaQueryWrapper<SysFileInfo> innerWrapper;
        List<BotEatingListVo> result = new ArrayList<>();
        BotEatingListVo vo;
        for (BotEating item : list) {
            innerWrapper = new LambdaQueryWrapper<>();
            vo = new BotEatingListVo();
            Integer refId = item.getId();
            BeanUtils.copyProperties(item, vo);
            innerWrapper.eq(SysFileInfo::getRefId, refId)
                    .eq(SysFileInfo::getRefType, SysFileTypeEnums.EATING.getValue())
                    .orderByAsc(SysFileInfo::getFileIndex);
            List<SysFileInfo> sysFileInfos = sysFileInfoService.list(innerWrapper);
            vo.setSysFileInfos(sysFileInfos);
            SysUser sysUser = sysUserService.selectUserById(item.getUserId());
            vo.setAvatar(sysUser.getAvatar());
            vo.setNickName(sysUser.getNickName());
            result.add(vo);
        }
        return result;
    }

    @Override
    public List<BotEatingOwnListVo> ownList(BotEatingListDTO dto) {
        LambdaQueryWrapper<BotEating> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BotEating::getUserId, SecurityUtils.getUserId())
                .eq(BotEating::getGroupId, dto.getGroupId())
                .orderByDesc(BotEating::getCreateTime);
        List<BotEating> list = baseMapper.selectList(wrapper);
        List<BotEatingListVo> result = this.getSysFile(list);
        Map<Integer, Map<Integer, List<BotEatingListVo>>> groupedData = result.stream().collect(Collectors.groupingBy(botEating -> botEating.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().getYear(), Collectors.groupingBy(botEating -> botEating.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().getMonthValue())));
        List<BotEatingOwnListVo> ownListVos = new ArrayList<>();
        for (Map.Entry<Integer, Map<Integer, List<BotEatingListVo>>> yearEntry : groupedData.entrySet()) {
            Integer year = yearEntry.getKey();
            Map<Integer, List<BotEatingListVo>> monthMap = yearEntry.getValue();
            BotEatingOwnListVo innerOwnListVoOfYear = new BotEatingOwnListVo();
            innerOwnListVoOfYear.setKey(year);
            List<BotEatingOwnListVo> ownListOfYear = new ArrayList<>();
            for (Map.Entry<Integer, List<BotEatingListVo>> monthEntry : monthMap.entrySet()) {
                Integer month = monthEntry.getKey();
                List<BotEatingListVo> value = monthEntry.getValue();
                BotEatingOwnListVo innerOwnListVoOfMonth = new BotEatingOwnListVo();
                innerOwnListVoOfMonth.setKey(month);
                List<SysFileInfo> collect = value.stream().flatMap(inner -> inner.getSysFileInfos().stream()).sorted(Comparator.comparing(SysFileInfo::getCreateTime).reversed()).collect(Collectors.toList());
                innerOwnListVoOfMonth.setSysFileInfos(collect);
                ownListOfYear.add(innerOwnListVoOfMonth);
            }
            List<BotEatingOwnListVo> monthCollect = ownListOfYear.stream().sorted(Comparator.comparing(BotEatingOwnListVo::getKey).reversed()).collect(Collectors.toList());
            innerOwnListVoOfYear.setBotEatingOwnList(monthCollect);
            ownListVos.add(innerOwnListVoOfYear);

        }
        return ownListVos.stream().sorted(Comparator.comparing(BotEatingOwnListVo::getKey).reversed()).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void add(BotEatingAddDTO dto) {
        Long userId = SecurityUtils.getUserId();
        String nickName = SecurityUtils.getLoginUser().getUser().getNickName();
        BotEating botEating = new BotEating();
        BeanUtils.copyProperties(dto, botEating);
        botEating.setUserId(userId);
//        botEating.setCreateParams();
        if (baseMapper.insert(botEating) != 0) {
            List<SysFileInfo> sysFileInfos = dto.getSysFileInfos();
            sysFileInfos.forEach(item -> {
                item.setId(IdUtils.simpleUUID());
                item.setRefType(SysFileTypeEnums.EATING.getValue());
                item.setRefId(botEating.getId());
//                item.setCreateParams();
            });
            sysFileInfoService.saveBatch(sysFileInfos);
            String noticeTitle = nickName + "发布了一条" + Constant.FOOD_SHARING;
            noticeUtils.systemPush(botEating.getId(), noticeTitle, NoticeTypeEnums.EATING_PUBLISH, Constant.EATING, nickName + "的" + Constant.FOOD_SHARING, botEating.getCreateTime(), dto.getGroupId());
        }
    }

    @Override
    public void update(BotEatingUpdateDTO dto) {
        BotEating botEating = new BotEating();
        BeanUtils.copyProperties(dto, botEating);
//        botEating.setUpdateParams();
        baseMapper.updateById(botEating);
    }

    @Override
    public void remove(BotEatingUpdateDTO dto) {
        BotEating botEating = new BotEating();
        BeanUtils.copyProperties(dto, botEating);
//        botEating.setUpdateParams();
        baseMapper.deleteById(botEating);
    }
}




